#ifndef BMP280_H
#define BMP280_H

#include <stdint.h>
#include <stddef.h>
#include <math.h>
#include <string.h>
#include "esp_log.h"
#include "esp_check.h"
#include "driver/i2c_master.h"
#include "driver/gpio.h"

/* Control reg 0xF4 */
typedef enum
{
    BMP280_TEMP_OVERSAMPLE_SKIP = (0<<5),
    BMP280_TEMP_OVERSAMPLE_X1   = (1<<5),
    BMP280_TEMP_OVERSAMPLE_X2   = (2<<5),
    BMP280_TEMP_OVERSAMPLE_X4   = (3<<5),
    BMP280_TEMP_OVERSAMPLE_X8   = (4<<5),
    BMP280_TEMP_OVERSAMPLE_X16  = (5<<5)
}BMP280_osrs_t_t;

typedef enum
{
    BMP280_PRESS_OVERSAMPLE_SKIP = (0<<2),
    BMP280_PRESS_OVERSAMPLE_X1   = (1<<2),
    BMP280_PRESS_OVERSAMPLE_X2   = (2<<2),
    BMP280_PRESS_OVERSAMPLE_X4   = (3<<2),
    BMP280_PRESS_OVERSAMPLE_X8   = (4<<2),
    BMP280_PRESS_OVERSAMPLE_X16  = (5<<2)
}BMP280_osrs_p_t;

typedef enum
{
    BMP280_SLEEP_MODE  = 0,
    BMP280_FORCED_MODE = 1,
    BMP280_NORMAL_MODE = 3
}BMP280_Operating_Mode_t;

/* Control reg 0xF5 */
typedef enum
{
    BMP280_STANDBY_TIME_0ms5  = (0<<5),
    BMP280_STANDBY_TIME_62ms5 = (1<<5),
    BMP280_STANDBY_TIME_125ms = (2<<5),
    BMP280_STANDBY_TIME_250ms = (3<<5),
    BMP280_STANDBY_TIME_500ms = (4<<5),
    BMP280_STANDBY_TIME_1Kms  = (5<<5),
    BMP280_STANDBY_TIME_2Kms  = (6<<5),
    BMP280_STANDBY_TIME_4Kms  = (7<<5)
}BMP280_t_sb_t;

typedef enum
{
    BMP280_FILTER_OFF = (0<<2),
    BMP280_FILTER_X2  = (1<<2),
    BMP280_FILTER_X4  = (2<<2),
    BMP280_FILTER_X8  = (3<<2),
    BMP280_FILTER_X16 = (4<<2)
}BMP280_filter_t;

typedef enum
{
    BMP280_SPI3W_OFF = 0,
    BMP280_SPI3W_ON  = 1
}BMP280_spi3w_en_t;

typedef struct
{
    uint32_t SCL_Speed;
    uint8_t Addr;
    uint8_t is_initialized;
    BMP280_Operating_Mode_t PowerMode;
    BMP280_osrs_t_t Temp_os;
    BMP280_osrs_p_t Press_os;
    BMP280_t_sb_t StandByTime;
    BMP280_filter_t FilterMode;
    BMP280_spi3w_en_t Spi3State;
}BMP280_Object_t;


#define BMP280_I2C_ADDR_L       0x76U
#define BMP280_I2C_ADDR_H       0x77U

#define BMP280_ID               0x58U
#define BMP280_RESET_VALUE      0xB6U

/* Register Map Start */
#define BMP280_TEMP_XLSB        0xFCU
#define BMP280_TEMP_LSB         0xFBU
#define BMP280_TEMP_MSB         0xFAU

#define BMP280_PRESS_XLSB       0xF9U
#define BMP280_PRESS_LSB        0xF8U
#define BMP280_PRESS_MSB        0xF7U

#define BMP280_CONFIG           0xF5U
#define BMP280_CTRL_MEAS        0xF4U
#define BMP280_STATUS           0xF3U
#define BMP280_RESET_REG        0xE0U
#define BMP280_ID_REG           0xD0U
/* Register Map End */

/* Calibration Parameters Map Start */
#define BMP280_DIG_T1_LSB_REG   0x88
#define BMP280_DIG_T1_MSB_REG   0x89
#define BMP280_DIG_T2_LSB_REG   0x8A
#define BMP280_DIG_T2_MSB_REG   0x8B
#define BMP280_DIG_T3_LSB_REG   0x8C
#define BMP280_DIG_T3_MSB_REG   0x8D
#define BMP280_DIG_P1_LSB_REG   0x8E
#define BMP280_DIG_P1_MSB_REG   0x8F
#define BMP280_DIG_P2_LSB_REG   0x90
#define BMP280_DIG_P2_MSB_REG   0x91
#define BMP280_DIG_P3_LSB_REG   0x92
#define BMP280_DIG_P3_MSB_REG   0x93
#define BMP280_DIG_P4_LSB_REG   0x94
#define BMP280_DIG_P4_MSB_REG   0x95
#define BMP280_DIG_P5_LSB_REG   0x96
#define BMP280_DIG_P5_MSB_REG   0x97
#define BMP280_DIG_P6_LSB_REG   0x98
#define BMP280_DIG_P6_MSB_REG   0x99
#define BMP280_DIG_P7_LSB_REG   0x9A
#define BMP280_DIG_P7_MSB_REG   0x9B
#define BMP280_DIG_P8_LSB_REG   0x9C
#define BMP280_DIG_P8_MSB_REG   0x9D
#define BMP280_DIG_P9_LSB_REG   0x9E
#define BMP280_DIG_P9_MSB_REG   0x9F
/* Calibration Parameters Map End */

typedef struct
{
    unsigned short dig_T1;
    short dig_T2;
    short dig_T3;
    unsigned short dig_P1;
    short dig_P2;
    short dig_P3;
    short dig_P4;
    short dig_P5;
    short dig_P6;
    short dig_P7;
    short dig_P8;
    short dig_P9;
}BMP280_Cali_Data_t;

static BMP280_Cali_Data_t bmp280_calidata;

typedef struct
{
    int32_t ADC_T;
    int32_t ADC_P;
    int32_t t_fine;
    float_t Temp;
    float_t Press;
}BMP280_Data_t;


/* BMP280 Functions */
esp_err_t bmp280_read_reg(i2c_master_dev_handle_t dev_handle, uint8_t *reg, uint8_t *data, uint16_t len);
esp_err_t bmp280_write_reg(i2c_master_dev_handle_t dev_handle, uint8_t *reg, uint8_t *data);

i2c_master_dev_handle_t bmp280_init(i2c_master_bus_handle_t i2c_bus,BMP280_Object_t *pObj);
esp_err_t bmp280_deinit(i2c_master_dev_handle_t dev_handle,BMP280_Object_t *pObj);
esp_err_t bmp280_reset(i2c_master_dev_handle_t dev_handle);

esp_err_t bmp280_read_id(i2c_master_dev_handle_t dev_handle);
esp_err_t bmp280_read_status(i2c_master_dev_handle_t dev_handle);

esp_err_t bmp280_read_mode(i2c_master_dev_handle_t dev_handle,BMP280_Object_t *pObj);
esp_err_t bmp280_set_mode(i2c_master_dev_handle_t dev_handle,BMP280_Object_t *pObj,BMP280_Operating_Mode_t power_mode,BMP280_osrs_t_t temp_oversample,BMP280_osrs_p_t press_oversample);
esp_err_t bmp280_read_config(i2c_master_dev_handle_t dev_handle,BMP280_Object_t *pObj);
esp_err_t bmp280_set_config(i2c_master_dev_handle_t dev_handle,BMP280_Object_t *pObj,BMP280_t_sb_t tsb_cfg,BMP280_filter_t filter_cfg,BMP280_spi3w_en_t spi3w_cfg);

esp_err_t bmp280_get_calibration_data(i2c_master_dev_handle_t dev_handle,BMP280_Object_t *pObj,BMP280_Cali_Data_t *data_t);
esp_err_t bmp280_read_press(i2c_master_dev_handle_t dev_handle,BMP280_Object_t *pObj,BMP280_Data_t *data_t);
esp_err_t bmp280_read_temp(i2c_master_dev_handle_t dev_handle,BMP280_Object_t *pObj,BMP280_Data_t *data_t);
esp_err_t bmp280_read_data(i2c_master_dev_handle_t dev_handle,BMP280_Object_t *pObj,BMP280_Data_t *data_t);


# endif
